package com.butcher.framework.kernel.endpoint.http.transform.object;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;

import com.butcher.framework.kernel.constants.ErrorCode;
import com.butcher.framework.kernel.endpoint.http.transform.MessageContext;
import com.butcher.framework.kernel.exc.FastHttpException;
import com.butcher.framework.kernel.object.serialize.SerializeUtil;

public class ObjectTool {
	private static OBJChain chain;

	private static OBJHashMap hashmap = new OBJHashMap();

	private static OBJArrayList arrayList = new OBJArrayList();

	private static OBJArray array = new OBJArray();

	private static OBJObject object = new OBJObject();

	private static OBJPrimitive primitive = new OBJPrimitive();
	static {
		object.addChain(primitive);
		array.addChain(object);
		arrayList.addChain(array);
		hashmap.addChain(arrayList);

		setOBJChain(hashmap);
	}

	private static void setOBJChain(OBJChain chains) {
		chain = chains;
	}

	public static OBJChain getOBJChain() {
		return chain;
	}

	public static void read(MessageContext context) throws FastHttpException {
		DataInputStream input = new DataInputStream(context.getInputStream());
		Object[] args = null;
		try {
			String methodName = input.readUTF();
			byte objNum = input.readByte();
			args = new Object[objNum];
			for (byte i = 0; i < objNum; i++) {
				args[i] = SerializeUtil.readFields(input);
			}
			context.setParameterValues(args);
			List<Method> methods = context.getService().getMethod(methodName);
			//for (Method method : methods) {
			for(int j=0;j<methods.size()&&context.getMethod()==null;j++){
				Class<?>[] classes = methods.get(j).getParameterTypes();
				if (classes.length != args.length) {
					continue;
				}
				boolean isBreak = false;
				for (int i = 0; i < classes.length; i++) {
					if (null != args[i]
							&&! (args[i].getClass().getName()
									.equals(classes[i].getName())
							|| classes[i].isAssignableFrom(args[i].getClass()))) {
						isBreak = true;
						break;
					}
				}
				if (!isBreak) {
					context.setMethod(methods.get(j));
				}
			}
			if (null == context.getMethod()) {
				throw new NoSuchMethodException();
			}
		} catch (NoSuchMethodException e) {
			throw new FastHttpException(ErrorCode.ERROR_NO_SUCH_METHOD, e);
		} catch (Exception e) {
			throw new FastHttpException(ErrorCode.ERROR_OBJECT_TRANSFORM, e);
		} finally {
			if (null != input) {
				try {
					input.close();
				} catch (IOException e) {
					// NOP
				}
			}
		}
	}

	public static void write(MessageContext context) throws FastHttpException {
		Object result = context.getResult();
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream out = null;
		try {
			out = new DataOutputStream(baos);
			out.writeUTF(context.getResultCode());
			SerializeUtil.write(out, result);
			context.setResponseContent(baos.toByteArray());
		} catch (Exception e) {
			throw new FastHttpException(ErrorCode.ERROR_OBJECT_TRANSFORM, e);
		} finally {
			if (null != out) {
				try {
					out.close();
				} catch (IOException e) {
					// NOP
				}
			}
			if (null != baos) {
				try {
					baos.close();
				} catch (IOException e) {
					// NOP
				}
			}
		}
	}
}
